#include <algorithm/analytical_model/io/json/converter/shared/data/topology/geometry/Geometry.h>
#include <algorithm/analytical_model/io/json/converter/shared/data/topology/geometry/Rectangle3D.h>
#include <algorithm/analytical_model/io/json/converter/shared/utils/Vec3.h>

using namespace solar;

void solar::tag_invoke(const boost::json::value_from_tag& /*unused*/,
                       boost::json::value& json_value, const Rectangle3D& rectangle_3d)
{
    auto size = SOLAR_GET_VALUE(Rectangle3D, size_, rectangle_3d);
    auto normal = SOLAR_GET_VALUE(Rectangle3D, normal_, rectangle_3d);
    auto center = SOLAR_GET_VALUE(Rectangle3D, center_, rectangle_3d);
    constexpr auto type = io::json::internal::convertGeometryType(GeometryType::kGeometryRectangle3D);
    json_value = {
        {  "type",                            type},
        {  "size",   boost::json::value_from(size)},
        {"normal", boost::json::value_from(normal)},
        {"center", boost::json::value_from(center)}
    };
}

auto solar::tag_invoke(const boost::json::value_to_tag<Rectangle3D>& /*unused*/,
                       const boost::json::value& json_value) -> Rectangle3D
{
    const auto* value_ptr = json_value.if_object();
    if (value_ptr == nullptr)
    {
        return {};
    }
    Rectangle3D result;
    if (const auto* size_value = value_ptr->if_contains("size"); size_value != nullptr)
    {
        SOLAR_SET_VALUE(Rectangle3D, size_, boost::json::value_to<Vec3>(*size_value), result)
    }
    if (const auto* normal_value = value_ptr->if_contains("normal"); normal_value != nullptr)
    {
        SOLAR_SET_VALUE(Rectangle3D, normal_, boost::json::value_to<Vec3>(*normal_value), result)
    }
    if (const auto* center_value = value_ptr->if_contains("center"); center_value != nullptr)
    {
        SOLAR_SET_VALUE(Rectangle3D, center_, boost::json::value_to<Vec3>(*center_value), result)
    }
    return result;
}
